package com.example.aop;


import com.example.utils.ApiResult;
import com.example.utils.RedisLock;
import com.example.utils.RequestUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;

import javax.servlet.http.HttpServletRequest;
import java.util.UUID;
@Aspect
@Component
public class RepeatSubmitAspect {
    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    @Autowired
    RedisLock redisLock;

    @Pointcut("@annotation(noRepeatSubmit)")
    public void pointCut(NoRepeatSubmit noRepeatSubmit) {
    }

    @Around("pointCut(noRepeatSubmit)")
    public Object around(ProceedingJoinPoint joinPoint, NoRepeatSubmit noRepeatSubmit) throws Throwable {
        int lockSecond = noRepeatSubmit.lockTime();

        HttpServletRequest request = RequestUtils.getRequest();
        Assert.notNull(request, "request can't null");

        // 此处可以用token或者JSessionId
        String token = request.getHeader("Authorization");
        String path = request.getServletPath();
        String key = getKey(token, path);
        String clientId = getClientId();

        boolean isSuccess = redisLock.tryLock(key, clientId, lockSecond);
        logger.info("tryLock key = [{}], clientId = [{}]", key, clientId);

        if (isSuccess) {
            logger.info("tryLock Success, key[{}], clientId = [{}]", key, clientId);

            Object result;
            // 继续执行过程
            try {
                result =   joinPoint.proceed();

            } finally {
                redisLock.releaseLock(key, clientId);
                logger.info("releaseLock Success, key = [{}], clientId = [{}]", key, clientId);

            }
            return result;

        } else {
            logger.info("tryLock fail, key[{}]", key);

            return new ApiResult(200, "请忽重复提交", null);
        }

    }

    private String getKey(String token, String path) {
        return token + path;
    }

    private String getClientId() {
        return UUID.randomUUID().toString();
    }
}

